#pragma once

#include "task_command.h"

#include "kernel/interfaces/ILogger.h"

#include <QObject>
#include <QMutex>
#include <QWaitCondition>

#include <atomic>
#include <memory>
#include <queue>
#include <unordered_map>
#include <unordered_set>
#include <vector>

namespace base::tasking {

class DbWorkerThread;

/**
 * @brief 任务调度器，负责统一调度仓储异步任务
 */
class TaskManager : public QObject {
    Q_OBJECT
public:
    explicit TaskManager(int workerCount,
                         std::shared_ptr<kernel::ILogger> logger,
                         QObject* parent = nullptr);
    ~TaskManager() override;

    TaskHandle::Ptr enqueue(TaskCommand::Ptr command);

    void cancelTask(const QString& taskId);
    void cancelBatch(const QString& batchId);

    void stop();

signals:
    void queueLengthChanged(int pending, int active);
    void taskEnqueued(const QString& taskId);
    void taskCompleted(const QString& taskId);
    void taskFailed(const QString& taskId, const QString& message);

private:
    friend class DbWorkerThread;

    TaskCommand::Ptr takeNextCommand();
    void onTaskStarted(const TaskCommand::Ptr& command);
    void onTaskFinished(const TaskCommand::Ptr& command, TaskResult result);
    void scheduleRetry(const TaskCommand::Ptr& command);
    void requeue(const TaskCommand::Ptr& command);

    bool isStopping() const { return m_stopping.load(std::memory_order_relaxed); }
    std::pair<int, int> snapshotCounts() const;

    int m_workerCount = 0;
    std::shared_ptr<kernel::ILogger> m_logger;

    mutable QMutex m_queueMutex;
    QWaitCondition m_taskAvailable;
    std::priority_queue<TaskCommand::Ptr, std::vector<TaskCommand::Ptr>, TaskCommandComparator> m_queue;
    std::unordered_map<QString, TaskCommand::Ptr> m_pendingIndex;
    std::unordered_map<QString, TaskCommand::Ptr> m_runningTasks;
    std::unordered_set<QString> m_canceledTaskIds;
    std::unordered_set<QString> m_canceledBatchIds;

    int m_pendingTaskCount = 0;
    int m_activeTaskCount = 0;

    std::vector<std::unique_ptr<DbWorkerThread>> m_workers;
    std::atomic_bool m_stopping{false};
};

} // namespace base::tasking
